home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 5 / Apprentice-Release5.iso / Source Code / C / Games / Xconq 7.1.0 / src / xconq-7.1.0 / mac / machelp.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-07-07  |  18.0 KB  |  627 lines  |  [TEXT/R*ch]

  1. /* Help for the Mac interface to Xconq.
  2.    Copyright (C) 1992, 1993, 1994, 1995, 1996 Stanley T. Shebs.
  3.  
  4. Xconq is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation; either version 2, or (at your option)
  7. any later version.  See the file COPYING.  */
  8.  
  9. #include "conq.h"
  10. #include "macconq.h"
  11.  
  12. static pascal void draw_instructions_text(WindowPtr win, short ditem);
  13. static pascal void help_vscroll_fn(ControlHandle control, short code);
  14.  
  15. /* Globals for the instructions window. */
  16.  
  17. WindowPtr instructionswin = nil;
  18.  
  19. TEHandle instructions_text = nil;
  20.  
  21. UserItemUPP draw_instructions_text_proc;
  22.  
  23. /* Globals for the help window. */
  24.  
  25. DialogPtr helpwin = nil;
  26.  
  27. TEHandle helptopic = nil;
  28.  
  29. TEHandle helptext = nil;
  30.  
  31. ControlHandle helpvscrollbar;
  32.  
  33. ControlActionUPP help_vscroll_proc;
  34.  
  35. ControlHandle topicsbutton;
  36. ControlHandle helpbutton;
  37. ControlHandle prevbutton;
  38. ControlHandle nextbutton;
  39. ControlHandle backbutton;
  40.  
  41. static HelpNode *cur_help_node = NULL;
  42.  
  43. char *helpstring = NULL;
  44.  
  45. /* The help node that is the list of topics. */
  46.  
  47. static HelpNode *topics_help_node = NULL;
  48.  
  49. /* The help node that tells about how to use the help system. */
  50.  
  51. static HelpNode *help_help_node = NULL;
  52.  
  53. #define NODESTACKSIZE 50
  54.  
  55. HelpNode **nodestack;
  56.  
  57. int nodestackpos;
  58.  
  59. /* The instructions window. */
  60.  
  61. static pascal void
  62. draw_instructions_text(WindowPtr win, short ditem)
  63. {
  64.     GrafPtr oldport;
  65.     short itemtype;  Handle itemhandle;  Rect itemrect;
  66.  
  67.     GetDItem(instructionswin, diInstructionsText, &itemtype, &itemhandle, &itemrect);
  68.     GetPort(&oldport);
  69.     SetPort(instructionswin);
  70.     TextSize(14);
  71.     TEUpdate(&itemrect, instructions_text);
  72.     /* This makes the title item draw big. */
  73.     TextSize(18);
  74.     SetPort(oldport);
  75. }
  76.  
  77. /* Bring up the dialog with instructions on how to play. */
  78.  
  79. void
  80. instructions_dialog()
  81. {
  82.     int mainwidth, mainheight;
  83.     Rect tmprect;
  84.  
  85.     if (instructionswin == nil) {
  86.         create_instructions_dialog();
  87.     }
  88.     if (first_windows) {
  89.         get_main_screen_size(&mainwidth, &mainheight);
  90.         tmprect = instructionswin->portRect;
  91.         MoveWindow(instructionswin,
  92.                    mainwidth - (tmprect.right - tmprect.left) - 3,
  93.                    mainheight - (tmprect.bottom - tmprect.top) - 3,
  94.                    FALSE);
  95.     }
  96.     ShowWindow(instructionswin);
  97.     SelectWindow(instructionswin);
  98. }
  99.  
  100. void
  101. create_instructions_dialog()
  102. {
  103.     Obj *instructions, *rest;
  104.     char *str;
  105.     Str255 tmpstr;
  106.     Rect destrect, viewrect;
  107.     short itemtype;  Handle itemhandle;  Rect itemrect;
  108.     Scorekeeper *sk;
  109.  
  110.     if (draw_instructions_text_proc == NULL)
  111.       draw_instructions_text_proc = NewUserItemProc(draw_instructions_text);
  112.  
  113.     instructionswin = GetNewDialog(dInstructions, nil, (DialogPtr) -1L);
  114.     GetDItem(instructionswin, diInstructionsTitle, &itemtype, &itemhandle, &itemrect);
  115.     c2p(((mainmodule && mainmodule->title) ? mainmodule->title : ""), tmpstr);
  116.     SetIText(itemhandle, tmpstr);
  117.     GetDItem(instructionswin, diInstructionsText, &itemtype, &itemhandle, &itemrect);
  118.     SetDItem(instructionswin, diInstructionsText, itemtype, (Handle) draw_instructions_text_proc, &itemrect);
  119.     destrect = itemrect;
  120.     viewrect = itemrect;
  121.     SetPort(instructionswin);
  122.     /* All text will be in Times. */
  123.     /* (should put sizes in a resource so can be edited) */
  124.     TextFont(times);
  125.     TextSize(14);
  126.     instructions_text = TENew(&destrect, &viewrect);
  127.     TESetSelect(0, 32767, instructions_text);
  128.     TEDelete(instructions_text);
  129.     if (mainmodule) {
  130.         instructions = mainmodule->instructions;
  131.         if (instructions != lispnil) {
  132.             if (stringp(instructions)) {
  133.                 str = c_string(instructions);
  134.                 TEInsert(str, strlen(str), instructions_text);
  135.             } else if (consp(instructions)) {
  136.                 for (rest = instructions; rest != lispnil; rest = cdr(rest)) {
  137.                     if (stringp(car(rest))) {
  138.                         str = c_string(car(rest));
  139.                         /* An empty line is a line break. */
  140.                         if (strlen(str) == 0) {
  141. #ifdef THINK_C
  142.                             str = "\r";
  143. #else
  144.                             str = "\n";
  145. #endif
  146.                         }
  147.                         TEInsert(str, strlen(str), instructions_text);
  148.                         TESetSelect(32767, 32767, instructions_text);
  149.                         /* Insert a blank between strings if none present, since they are
  150.                            usually word breaks. */
  151.                         if (str[strlen(str)-1] != ' ')
  152.                           TEInsert(" ", 1, instructions_text);
  153.                         TESetSelect(32767, 32767, instructions_text);
  154.                     }
  155.                 }
  156.             } else {
  157.                 /* error? */
  158.             }
  159.         } else {
  160.             if (mainmodule->blurb) {
  161.                 str = mainmodule->blurb;
  162.                 TEInsert(str, strlen(str), instructions_text);
  163. #ifdef THINK_C
  164.                 str = "\r\r";
  165. #else
  166.                 str = "\n\n";
  167. #endif
  168.                 TEInsert(str, strlen(str), instructions_text);
  169.             }
  170.             str = "(no instructions supplied)";
  171.             TEInsert(str, strlen(str), instructions_text);
  172.             for_all_scorekeepers(sk) {
  173.                 /* (should add better scorekeeper descriptions) */
  174. #ifdef THINK_C
  175.                 str = "\r";
  176. #else
  177.                 str = "\n";
  178. #endif
  179.                 TEInsert(str, strlen(str), instructions_text);
  180.                 str = "a scorekeeper";
  181.                 TEInsert(str, strlen(str), instructions_text);
  182.             }
  183.         }
  184.     } else {
  185.         /* this should be impossible? */
  186.     }
  187.     /* This makes the title item draw big. */
  188.     TextSize(18);
  189.     add_window_menu_item("Instructions", instructionswin);
  190. }
  191.  
  192. int
  193. hit_instructions_dialog(DialogPtr dialog, int itemhit, EventRecord *evt)
  194. {
  195.     switch (itemhit) {
  196.         case diInstructionsHelp:
  197.             /* Just jump to the help dialog. */
  198.             help_dialog(NULL);
  199.             break;
  200.     }
  201.     return TRUE;
  202. }
  203.  
  204. /* Help window. */
  205.  
  206. /* This is the top-level access to bring up the help window, can be called
  207.    anywhere, anytime. */
  208.  
  209. void
  210. help_dialog(HelpNode *helpnode)
  211. {
  212.     if (helpwin == nil) {
  213.         create_help_window();
  214.     }
  215.     if (helpnode != NULL) {
  216.         cur_help_node = helpnode;
  217.         set_help_content(helpnode);
  218.     }
  219.     ShowWindow(helpwin);
  220.     SelectWindow(helpwin);
  221. }
  222.  
  223. void
  224. describe_menus(int arg, char *key, char *buf)
  225. {
  226.     strcat(buf, "File\n");
  227.     strcat(buf, "  The usual file operations.\n");
  228.     strcat(buf, "\n");
  229.     strcat(buf, "Edit\n");
  230.     strcat(buf, "  Select All selects all of your units at once.\n");
  231.     strcat(buf, "\n");
  232.     strcat(buf, "Find\n");
  233.     strcat(buf, "  Find Selected goes to the next map back and looks at the unit selected or viewed in the front window.\n");
  234.     strcat(buf, "\n");
  235.     strcat(buf, "Play\n");
  236.     strcat(buf, "  This is the main menu for unit actions.");
  237.     strcat(buf, "  Each item represents something that you can do to the currently selected units.\n");
  238.     strcat(buf, "  If an action is grayed out, then none of the selected units can do it.\n");
  239.     strcat(buf, "  Closeup shows details of the selected units.\n");
  240.     strcat(buf, "  Build brings up the construction dialog.\n");
  241.     strcat(buf, "Side\n");
  242.     strcat(buf, "  This menu is for things that affect your whole side.\n");
  243.     strcat(buf, "Windows\n");
  244.     strcat(buf, "  This menu does window control.\n");
  245.     strcat(buf, "View (when a map is front window)\n");
  246.     strcat(buf, "  Items toggle various display elements in the front map window.\n");
  247.     strcat(buf, "\n");
  248.     strcat(buf, "View (when a list is front window)\n");
  249.     strcat(buf, "  Items toggle various display elements in the front list window.\n");
  250.     strcat(buf, "\n");
  251. }
  252.  
  253. void
  254. describe_mouse(int arg, char *key, char *buf)
  255. {
  256.     strcat(buf, "In move-on-click mode:\n");
  257.     strcat(buf, "  The next unit that can do anything will be selected automatically.\n");
  258.     strcat(buf, "  Click once on a destination to move the selected unit there.\n");
  259.     strcat(buf, "\n");
  260.     strcat(buf, "In normal mode:\n");
  261.     strcat(buf, "  Click once on a unit to select it.\n");
  262.     strcat(buf, "  Drag to destination to move it.\n");
  263.     strcat(buf, "  Shift-click to select additional units.\n");
  264.     strcat(buf, "  Drag out rectangle to select all units inside.\n");
  265.     strcat(buf, "\n");
  266.     strcat(buf, "Command-click to moves all selected units to the clicked-on location.");
  267.     strcat(buf, "\n");
  268.     strcat(buf, "Combat is automatic if another side's unit is adjacent and clicked on.");
  269. }
  270.  
  271. void
  272. describe_keyboard(int arg, char *key, char *buf)
  273. {
  274.     describe_commands(arg, key, buf);
  275. }
  276.  
  277. void
  278. describe_help(int arg, char *key, char *buf)
  279. {
  280.     strcat(buf, "Xconq Help consists of a number of ``topics''.  ");
  281.     strcat(buf, "Topics include generic information about Xconq as ");
  282.     strcat(buf, "well as specific details of the game in progress.  ");
  283.     strcat(buf, "To navigate, click the buttons above.");
  284.     strcat(buf, "\n");
  285.     strcat(buf, "Topics: ");
  286.     strcat(buf, "Clicking this button shows you the list of topics.  ");
  287.     strcat(buf, "Clicking on a topic in the list takes you to it directly.");
  288.     strcat(buf, "\n");
  289.     strcat(buf, "Help:  ");
  290.     strcat(buf, "Clicking this button shows you the topic you're looking at right now.");
  291.     strcat(buf, "\n");
  292.     strcat(buf, "Next:  ");
  293.     strcat(buf, "Clicking this button goes to the next topic in order.");
  294.     strcat(buf, "\n");
  295.     strcat(buf, "Previous:  ");
  296.     strcat(buf, "Clicking this button goes to the previous topic in order.");
  297.     strcat(buf, "\n");
  298.     strcat(buf, "Back:  ");
  299.     strcat(buf, "Clicking this button goes to the last topic you were looking at.  ");
  300.     strcat(buf, "Multiple clicks take you farther and farther back.");
  301.     strcat(buf, "\n");
  302. }
  303.  
  304. void
  305. create_help_window()
  306. {
  307.     int h, v;
  308.     Rect helptopicrect, destrect, viewrect, vscrollrect;
  309.  
  310.     /* Create the window, color if possible, since images may be in color. */
  311.     if (hasColorQD) {    
  312.         helpwin = GetNewCWindow(wHelp, NULL, (WindowPtr) -1L);
  313.     } else {
  314.         helpwin = GetNewWindow(wHelp, NULL, (WindowPtr) -1L);
  315.     }
  316.     topicsbutton = GetNewControl(cTopicsButton, helpwin);
  317.     helpbutton = GetNewControl(cHelpButton, helpwin);
  318.     prevbutton = GetNewControl(cPrevButton, helpwin);
  319.     nextbutton = GetNewControl(cNextButton, helpwin);
  320.     backbutton = GetNewControl(cBackButton, helpwin);
  321.     SetPort(helpwin);
  322.     /* All text will be in Times. */
  323.     /* (should these be choosable?) */
  324.     TextFont(times);
  325.     /* Set up the topic title. */
  326.     TextSize(18);
  327.     SetRect(&helptopicrect, 45, 45, 305, 75); 
  328.     helptopic = TENew(&helptopicrect, &helptopicrect);
  329.     /* Set up the help text proper. */
  330.     TextSize(14);
  331.     h = window_width(helpwin);  v = window_height(helpwin);
  332.     SetRect(&viewrect, 5, 75, h - sbarwid, v - sbarwid); 
  333.     destrect = viewrect;
  334.     helptext = TENew(&destrect, &destrect);
  335.     /* Set up a vertical scrollbar. */
  336.     vscrollrect = helpwin->portRect;
  337.     vscrollrect.top = 75;
  338.     vscrollrect.bottom -= sbarwid - 1;
  339.     vscrollrect.left = vscrollrect.right - sbarwid;
  340.     vscrollrect.right += 1;
  341.     helpvscrollbar =
  342.         NewControl(helpwin, &vscrollrect, "\p", TRUE, 0, 0, 0, scrollBarProc, 0L);
  343.     HiliteControl(helpvscrollbar, 0);
  344.     /* Add the Mac-specific help nodes. */
  345.     /* (Note that these will appear in *reverse* order from here, because each
  346.        is being glued right after the first help node. */
  347.     add_help_node("menus", describe_menus, 0, first_help_node);
  348.     add_help_node("mouse", describe_mouse, 0, first_help_node);
  349.     add_help_node("keyboard", describe_keyboard, 0, first_help_node);
  350.     help_help_node = add_help_node("help", describe_help, 0, first_help_node);
  351.     topics_help_node = add_help_node("topics", describe_topics, 0, first_help_node);
  352.     cur_help_node = topics_help_node;
  353.     set_help_content(cur_help_node);
  354.     if (nodestack == NULL)
  355.       nodestack = (HelpNode **) xmalloc(NODESTACKSIZE * sizeof(HelpNode *));
  356.     nodestackpos = 0;
  357.     add_window_menu_item("Help", helpwin);
  358. }
  359.  
  360. void
  361. set_help_content(HelpNode *curnode)
  362. {
  363.     char *str;
  364.  
  365.     get_help_text(curnode);
  366.     /* Set the displayed topic title. */
  367.     TESetSelect(0, 32767, helptopic);
  368.     TECut(helptopic);
  369.     /* Copy in the new help topic text. */
  370.     TESetText(curnode->key, strlen(curnode->key), helptopic);
  371.     /* Set the displayed text. */
  372.     str = curnode->text;
  373. #ifdef THINK_C
  374.     /* Hack up newlines so that TextEdit recognizes them. */
  375.     {
  376.         int i, len = strlen(str);
  377.     
  378.         for (i = 0; i < len; ++i) {
  379.             if (str[i] == '\n')
  380.               str[i] = '\r';
  381.         }
  382.     }
  383. #endif
  384.     helpstring = str;
  385.     /* Remove all the existing text. */
  386.     TESetSelect(0, 32767, helptext);
  387.     TECut(helptext);
  388.     /* Copy in the new help text. */
  389.     TESetText(helpstring, strlen(helpstring), helptext);
  390.     (*helptext)->destRect = (*helptext)->viewRect;
  391.     /* Update on the screen. */
  392.     draw_help();
  393.     adjust_help_scrollbar();
  394. }
  395.  
  396. void
  397. draw_help()
  398. {
  399.     Rect tmprect;
  400.     GrafPtr oldport;
  401.  
  402.     GetPort(&oldport);
  403.     SetPort(helpwin);
  404.     SetRect(&tmprect, 5, 40, 5 + 32, 40 + 32);
  405.     EraseRect(&tmprect);
  406.     if (cur_help_node->nclass == utypenode && is_unit_type(cur_help_node->arg)) {
  407.         draw_unit_image(helpwin, tmprect.left, tmprect.top, 32, 32,
  408.                         cur_help_node->arg, -1, 0);
  409.     } else if (cur_help_node->nclass == ttypenode && is_terrain_type(cur_help_node->arg)) {
  410.         draw_terrain_sample(helpwin, tmprect, cur_help_node->arg); 
  411.     }
  412.     TextSize(18);
  413.     TEUpdate(&(helpwin->portRect), helptopic);
  414.     TextSize(14);
  415.     TEUpdate(&(helpwin->portRect), helptext);
  416.     SetPort(oldport);
  417.     adjust_help_scrollbar();
  418. }
  419.  
  420. void
  421. adjust_help_scrollbar()
  422. {
  423.     int lines, newmax, value;
  424.  
  425.     lines = (*helptext)->nLines;
  426.     newmax = lines - (((*helptext)->viewRect.bottom - (*helptext)->viewRect.top)
  427.                      / (*helptext)->lineHeight);
  428.     if (newmax < 0) newmax = 0;
  429.     SetCtlMax(helpvscrollbar, newmax);
  430.     value = ((*helptext)->viewRect.top - (*helptext)->destRect.top)
  431.             / (*helptext)->lineHeight;
  432.     SetCtlValue(helpvscrollbar, value);
  433. }
  434.  
  435. void
  436. activate_help(int activate)
  437. {
  438.     HiliteControl(helpvscrollbar, (activate ? 0 : 255));
  439. }
  440.  
  441. static pascal void
  442. help_vscroll_fn(ControlHandle control, short code)
  443. {
  444.     int oldvalue, curvalue, minvalue, maxvalue, pagesize, jump;
  445.  
  446.     curvalue = GetCtlValue(control);
  447.     minvalue = GetCtlMin(control);
  448.     maxvalue = GetCtlMax(control);
  449.     pagesize = ((*helptext)->viewRect.bottom - (*helptext)->viewRect.top) /
  450.                 (*helptext)->lineHeight;
  451.     if (pagesize > 1) pagesize -= 1;
  452.     switch (code) {
  453.         case inPageDown:
  454.             jump = pagesize;
  455.             break;
  456.         case inDownButton:
  457.             jump = 1;
  458.             break;
  459.         case inPageUp:
  460.             jump = - pagesize;
  461.             break;
  462.         case inUpButton:
  463.             jump = -1;
  464.             break;
  465.         default:
  466.             jump = 0;
  467.             break;
  468.     }
  469.     oldvalue = curvalue;
  470.     curvalue = max(min(curvalue + jump, maxvalue), minvalue);
  471.     SetCtlValue(control, curvalue);
  472.     /* Calculate the actual jump and use it to adjust the text. */
  473.     jump = curvalue - oldvalue;
  474.     if (jump != 0)
  475.       TEScroll(0, - jump * (*helptext)->lineHeight, helptext);
  476. }
  477.  
  478. /* Respond to an event occurring in the help window. */
  479.  
  480. void
  481. do_mouse_down_help(Point mouse, int mods)
  482. {
  483.     ControlHandle control;
  484.     short part, value;
  485.     int i;
  486.     HelpNode *prevhelpnode = cur_help_node, *helpnode;
  487.  
  488.     if (help_vscroll_proc == NULL)
  489.       help_vscroll_proc = NewControlActionProc(help_vscroll_fn);
  490.  
  491.     part = FindControl(mouse, helpwin, &control);
  492.     if (control == topicsbutton) {
  493.         cur_help_node = topics_help_node;
  494.     } else if (control == helpbutton) {
  495.         cur_help_node = help_help_node;
  496.     } else if (control == prevbutton) {
  497.         cur_help_node = cur_help_node->prev;
  498.     } else if (control == nextbutton) {
  499.         cur_help_node = cur_help_node->next;
  500.     } else if (control == backbutton) {
  501.         if (nodestackpos > 0) {
  502.             cur_help_node = nodestack[--nodestackpos];
  503.         }
  504.     } else if (control == helpvscrollbar) {
  505.         if (part != 0) {
  506.             switch (part) {
  507.                 case inPageDown:
  508.                 case inDownButton:
  509.                 case inPageUp:
  510.                 case inUpButton:
  511.                     value = TrackControl(control, mouse, (ControlActionUPP) help_vscroll_proc);
  512.                     break;
  513.                 case inThumb:
  514.                     value = GetCtlValue(control);
  515.                     if ((part = TrackControl(control, mouse, nil)) != 0) {
  516.                         value -= GetCtlValue(control);
  517.                         if (value != 0) {
  518.                             TEScroll(0, value * (*helptext)->lineHeight, helptext);
  519.                         }
  520.                     }
  521.                     break;
  522.             }
  523.         }
  524.     } else if (PtInRect(mouse, &((*helptext)->viewRect))) {
  525.         TEClick(mouse, 0, helptext);
  526.         if (cur_help_node == topics_help_node) {
  527.             char strbuf[100], *cr1, *cr2;
  528.             int selstart = (*helptext)->selStart, selend = (*helptext)->selEnd;
  529.             CharsHandle chars = TEGetText(helptext);
  530.  
  531.             if (selstart == selend) {
  532.                 if (strchr("\r\n", *((*chars)+selstart)))
  533.                   --selstart;
  534.                 /* Manufacture a "selection" of the line clicked in. */
  535.                 for (cr1 = (*chars)+selstart; cr1 != (*chars); --cr1)
  536.                   if (strchr("\r\n", *cr1))
  537.                     break;
  538.                 cr2 = strchr((*chars)+selstart, '\r');
  539.                 if (cr2 == NULL)
  540.                   cr2 = strchr((*chars)+selstart, '\n');
  541.                 selstart = (cr1 != NULL ? cr1 - (*chars) + 1 : 0);
  542.                 selend = (cr2 != NULL ? cr2 - (*chars) : 0);
  543.                 if (selstart > selend)
  544.                   selstart = selend;
  545.             }
  546.             if (selstart != selend) {
  547.                 strncpy(strbuf, (*chars)+selstart, selend - selstart);
  548.                 strbuf[selend - selstart] = '\0';
  549.                 helpnode = find_help_node(cur_help_node, strbuf);
  550.                 if (helpnode != NULL) {
  551.                     cur_help_node = helpnode;
  552.                 } else {
  553.                     beep();
  554.                 }
  555.             } else {
  556.                 beep();
  557.             }
  558.         }
  559.     }
  560.     /* If we changed help nodes, get its contents and record on the node stack. */
  561.     if (prevhelpnode != cur_help_node) {
  562.         set_help_content(cur_help_node);
  563.         if (control != backbutton) {
  564.             if (nodestackpos >= NODESTACKSIZE) {
  565.                 for (i = 1; i < NODESTACKSIZE; ++i) nodestack[i - 1] = nodestack[i];
  566.                 nodestackpos = NODESTACKSIZE - 1;
  567.             }
  568.             nodestack[nodestackpos++] = prevhelpnode;
  569.         }
  570.     }
  571. }
  572.  
  573. void
  574. grow_help(int h, int v)
  575. {
  576.     EraseRect(&helpwin->portRect);
  577.     SizeWindow(helpwin, h, v, 1);
  578.     MoveControl(helpvscrollbar, h - sbarwid, 75);
  579.     SizeControl(helpvscrollbar, sbarwid + 1, v - 75 - sbarwid + 1);
  580.     (*helptext)->viewRect.right = h - sbarwid;
  581.     (*helptext)->viewRect.bottom = v - sbarwid;
  582.     (*helptext)->destRect.right = h - sbarwid;
  583.     TECalText(helptext);
  584.     InvalRect(&helpwin->portRect);
  585. }                    
  586.  
  587. void
  588. zoom_help(int part)
  589. {
  590.     int titleh, h, v;
  591.     Rect zoomrect;
  592.     GDHandle gd, zoomgd;
  593.  
  594.     EraseRect(&helpwin->portRect);
  595.     if (part == inZoomOut) {
  596.         if (hasColorQD) {
  597.             zoomgd = best_zoom_screen(&helpwin->portRect);
  598.             zoomrect = (*zoomgd)->gdRect;
  599.             if (zoomgd == GetMainDevice()) {
  600.                 zoomrect.top += GetMBarHeight();
  601.             }
  602.             titleh = 20; /* (should calc) */
  603.             zoomrect.top += titleh;
  604.             InsetRect(&zoomrect, 3, 3);
  605.         } else {
  606.             /* If no Color QD, then there is only the one screen. */
  607.             zoomrect = QD(screenBits).bounds;
  608.             zoomrect.top += GetMBarHeight();
  609.             titleh = 20; /* (should calc) */
  610.             zoomrect.top += titleh;
  611.             InsetRect(&zoomrect, 4, 4);
  612.         }
  613.         (*((WStateDataHandle) ((WindowPeek) helpwin)->dataHandle))->stdState = zoomrect;
  614.     }
  615.     ZoomWindow(helpwin, part, (helpwin == FrontWindow()));
  616.     h = window_width(helpwin);  v = window_height(helpwin);
  617.     MoveControl(helpvscrollbar, h - sbarwid, 0);
  618.     SizeControl(helpvscrollbar, sbarwid + 1, v - sbarwid + 1);
  619.     adjust_help_scrollbar();
  620.     (*helptext)->viewRect.right = h - sbarwid;
  621.     (*helptext)->viewRect.bottom = v - sbarwid;
  622.     (*helptext)->destRect.right = h - sbarwid;
  623.     TECalText(helptext);
  624.     /* This will force a full redraw at the next update. */
  625.     InvalRect(&helpwin->portRect);
  626. }
  627.